#include "protocol.h"
#include "uart_fifo.h"
#include "comfun.h"
#include <string.h>
static unsigned char global_ser = 0;
static unsigned short frame_did;
int peek_len;

static int iap_start(proto_188_t  *proto,uint8_t buff[],uint8_t w_len, uint16_t did)
{
	return 0;
}

static int set_low_baud(proto_188_t  *proto,uint8_t buff[],uint8_t w_len, uint16_t did)
{
	return 1;
}

const proto_188_item_t  proto_188_item_list[]=
{
    {test_did, 						NULL, 								NULL,									-1},
	{IAP_START, 					NULL , 				     			iap_start,									-1},
};


int get_188_frame(unsigned char rxframe_raw[],int rxlen,int *call_my_addr,int *boardcast_my)
{
    int  i = 0,datalen;
    uint8_t cs;
    int framelen;
    unsigned char devid[7];

    if (rxlen < 9) return(-1);
check_frame:

    *call_my_addr = 0;
    *boardcast_my = 0;
    while(i < rxlen)
    {
        if(0x68 == rxframe_raw[i])//188 head
            break;
        i++;
    }
    if(i>=rxlen) return(-1);//if not 118 head return -1
    framelen = rxlen - i;// frame len

    if((!(is_all_xx(&rxframe_raw[i + 1 ],1, 0x10))) && (!(is_all_xx(&rxframe_raw[i + 1 ],1, 0xAA))))//if not water or boardcast
    {
        return (-1);
    }

    if (framelen >= 9)
    {
        if (0 == memcmp(&rxframe_raw[i + 2 ],devid, 7))//address equal
        {
            if(call_my_addr)  *call_my_addr = 1;
        }
        if(is_all_xx(&rxframe_raw[i + 2 ],0xAA, 7))//boardcast
        {
            if(boardcast_my) *boardcast_my = 1;
        }
    }
    if (framelen < 11)  return (-1);
    datalen = rxframe_raw[i+10];//datalen
    if (datalen + 11 + 2 > framelen)
    {
        i++;
        goto check_frame;
    }
    cs = checksum(rxframe_raw+i, datalen  + 11 );
    if(rxframe_raw[i + datalen  + 11 ] != cs)
    {
        i++;
        goto check_frame;
    }
    if(rxframe_raw[i + datalen  + 11 + 1] != 0x16)//not equal end symbol
    {
        i++;
        goto check_frame;
    }
    return(i);
}

int handle_write_read_cmd(unsigned char data[])
{
    int task =0;
    int i=0;

    const proto_188_item_t *item = NULL;
    proto_188_t  *proto = (proto_188_t *)data;
    unsigned short reverse_did = ((proto->did[0] & 0xff) << 8) + proto->did[1];
    unsigned short normal_did = ((proto->did[1] & 0xff) << 8) + proto->did[0];
    frame_did = normal_did;
    global_ser = proto->data[0];
    for (i=0; i < ARRAY_SIZE(proto_188_item_list); i++)
    {
        item = &proto_188_item_list[i];
        if(item->did == reverse_did || item->did == normal_did)
        {
            switch(proto->cmd)
            {
            case CMD_188_READ:
                if(NULL != item->read)
                {
                    task = item->read(proto,proto->data+1,proto->len-3,30,normal_did);
                }
                else
                {
                    task = item->dafault_task;
                }
                break;
            case CMD_188_READ_ADDRESS:
                if(NULL != item->read)
                {
                    task = item->read(proto,proto->data+1,proto->len-3,30,normal_did);
                }
                else
                {
                    task = item->dafault_task;
                }
                break;
            case CMD_188_SET_ADDRESS:
                if(NULL != item->write)
                {
                    task = item->write(proto,proto->data+1,proto->len-3,normal_did);
                }
                break;
            case CMD_188_WRITE:
                if(NULL != item->write)
                {
                    task = item->write(proto,proto->data+1,proto->len-3,normal_did);
                }
                else
                {
                    task = item->dafault_task;
                }
                break;
            default :
                break;
            }
        }
    }
    if(task < 0)
    {

    }

    return task;
}

int handle_proto_188_task(void)
{

    uint8_t buffer[255];
    int idx,framelen;
    int call_me= 0;
    int boardcast = 0;
    int task;
    /*从串口缓冲区中读数据*/
    peek_len = uart_peek_rx_chn(0,buffer,sizeof(buffer));
    /*寻找完整帧*/
    idx = get_188_frame(buffer,peek_len,&call_me,&boardcast);
    if (idx >= 0)
    {
        if ((call_me) || (boardcast))//call me or boardcast
        {
            framelen =  buffer[idx+10] +11 + 2;
            uart_get_rx_chn(0,buffer,idx);
            uart_get_rx_chn(0,buffer,framelen);
            /*处理完整帧*/
            task = handle_write_read_cmd(buffer);
            if (task > 0)
            {
                return (task);
            }
        }
        else  //188frame not for me
        {
            return (0);
        }
    }
    return (0);


}

